<template>
  <div>
    <div ref="container" id="container"></div>
  </div>
</template>

<script setup>
import { MMDAnimationHelper } from "three/examples/jsm/animation/MMDAnimationHelper.js";
import { MMDLoader } from "three/examples/jsm/loaders/MMDLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import * as THREE from "three";
import { onMounted, reactive, ref, onUnmounted } from "vue";

const container = ref(null);

let scene, camera, renderer, clock;
let frameId;
let helper;
let modelMesh;
let loader;
let gui;
let spotLight;

// 动作配置
const animations = {
  'TW动作': '/move/tw.vmd',
  'Ayaka舞蹈': '/move/ayaka-dance.vmd'
};

// GUI控制参数
const guiParams = {
  animation: 'TW动作',
  spotLight: {
    intensity: 1.0,
    distance: 100,
    angle: Math.PI / 6,
    penumbra: 0.2,
    decay: 2,
    position: {
      x: 10,
      y: 20,
      z: 10
    },
    target: {
      x: 0,
      y: 10,
      z: 0
    }
  }
};

let initialModelLoaded = false;

// 加载新动画的函数
function loadAnimation(animationPath) {
  // 从场景中移除当前模型
  if (modelMesh) {
    // 首先从helper中移除模型
    if (helper) {
      helper.remove(modelMesh);
    }
    scene.remove(modelMesh);
  }
  
  // 创建新的helper实例
  helper = new MMDAnimationHelper();
  
  // 重新加载模型和动画
  loader.loadWithAnimation(
    "/qque/青雀（分桦）.pmx",
    animationPath,
    function onLoad(mmd) {
      modelMesh = mmd.mesh;
      
      helper.add(mmd.mesh, {
        animation: mmd.animation,
        physics: true
      });

      scene.add(mmd.mesh);
      
      // 更新聚光灯目标到模型位置
      updateSpotLightTarget();
    },
    onProgress,
    function(error) {
      console.error('加载模型或动画出错:', error);
    }
  );
}

function onProgress(xhr) {
  if (xhr.lengthComputable) {
    const percentComplete = xhr.loaded / xhr.total * 100;
    console.log(Math.round(percentComplete) + '% 已下载');
  }
}

// 更新聚光灯目标位置
function updateSpotLightTarget() {
  if (spotLight && modelMesh) {
    spotLight.target.position.set(
      guiParams.spotLight.target.x,
      guiParams.spotLight.target.y,
      guiParams.spotLight.target.z
    );
    spotLight.target.updateMatrixWorld();
  }
}

// 设置GUI控制面板
function setupGUI() {
  gui = new GUI();
  gui.title('MMD Demo 10 控制面板');
  
  // 动画控制
  const animationFolder = gui.addFolder('动画控制');
  animationFolder.add(guiParams, 'animation', Object.keys(animations)).onChange((value) => {
    const animationPath = animations[value];
    loadAnimation(animationPath);
  });
  animationFolder.open();
  
  // 聚光灯控制
  const lightFolder = gui.addFolder('聚光灯控制');
  
  // 光照强度和基本参数
  lightFolder.add(guiParams.spotLight, 'intensity', 0, 3, 0.1).onChange((value) => {
    if (spotLight) spotLight.intensity = value;
  });
  
  lightFolder.add(guiParams.spotLight, 'distance', 0, 200, 5).onChange((value) => {
    if (spotLight) spotLight.distance = value;
  });
  
  lightFolder.add(guiParams.spotLight, 'angle', 0, Math.PI / 2, 0.01).onChange((value) => {
    if (spotLight) spotLight.angle = value;
  });
  
  lightFolder.add(guiParams.spotLight, 'penumbra', 0, 1, 0.01).onChange((value) => {
    if (spotLight) spotLight.penumbra = value;
  });
  
  lightFolder.add(guiParams.spotLight, 'decay', 1, 5, 0.1).onChange((value) => {
    if (spotLight) spotLight.decay = value;
  });
  
  // 光照位置控制
  const positionFolder = lightFolder.addFolder('光源位置');
  positionFolder.add(guiParams.spotLight.position, 'x', -50, 50, 1).onChange((value) => {
    if (spotLight) spotLight.position.x = value;
  });
  positionFolder.add(guiParams.spotLight.position, 'y', 0, 50, 1).onChange((value) => {
    if (spotLight) spotLight.position.y = value;
  });
  positionFolder.add(guiParams.spotLight.position, 'z', -50, 50, 1).onChange((value) => {
    if (spotLight) spotLight.position.z = value;
  });
  positionFolder.open();
  
  // 光照目标控制
  const targetFolder = lightFolder.addFolder('光照目标');
  targetFolder.add(guiParams.spotLight.target, 'x', -20, 20, 1).onChange((value) => {
    updateSpotLightTarget();
  });
  targetFolder.add(guiParams.spotLight.target, 'y', 0, 30, 1).onChange((value) => {
    updateSpotLightTarget();
  });
  targetFolder.add(guiParams.spotLight.target, 'z', -20, 20, 1).onChange((value) => {
    updateSpotLightTarget();
  });
  targetFolder.open();
  
  lightFolder.open();
}

onMounted(() => {
  // 相机位置的响应式数据
  const cameraPosition = reactive({
    x: 0,
    y: 0,
    z: 75,
  });
  const width = window.innerWidth;
  const height = window.innerHeight;
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(750, width / height, 0.1, 2000);
  loader = new MMDLoader();
  
  // 添加环境光
  const ambientLight = new THREE.AmbientLight(0x404040, 0.3);
  scene.add(ambientLight);
  
  // 添加聚光灯
  spotLight = new THREE.SpotLight(0xffffff, guiParams.spotLight.intensity);
  spotLight.position.set(
    guiParams.spotLight.position.x,
    guiParams.spotLight.position.y,
    guiParams.spotLight.position.z
  );
  spotLight.distance = guiParams.spotLight.distance;
  spotLight.angle = guiParams.spotLight.angle;
  spotLight.penumbra = guiParams.spotLight.penumbra;
  spotLight.decay = guiParams.spotLight.decay;
  spotLight.castShadow = true;
  
  // 设置阴影属性
  spotLight.shadow.mapSize.width = 2048;
  spotLight.shadow.mapSize.height = 2048;
  spotLight.shadow.camera.near = 0.5;
  spotLight.shadow.camera.far = 500;
  
  scene.add(spotLight);
  scene.add(spotLight.target);
  
  // 添加聚光灯助手（可选，用于调试）
  // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  // scene.add(spotLightHelper);

  camera.position.set(cameraPosition.x, cameraPosition.y, cameraPosition.z);

  helper = new MMDAnimationHelper();
  
  // 在这里加载初始模型和动画
  loader.loadWithAnimation(
    "/qque/青雀（分桦）.pmx",
    animations[guiParams.animation],
    function onLoad(mmd) {
      modelMesh = mmd.mesh;
      initialModelLoaded = true;
      
      helper.add(mmd.mesh, {
        animation: mmd.animation,
        physics: true
      });

      scene.add(mmd.mesh);
      
      // 初始化聚光灯目标
      updateSpotLightTarget();
    },
    onProgress,
    function(error) {
      console.error('加载初始模型或动画出错:', error);
    }
  );

  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
  renderer.setSize(width, height);
  renderer.setClearColor(new THREE.Color(0x000000));
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  clock = new THREE.Clock();

  container.value.appendChild(renderer.domElement);

  const controls = new OrbitControls(camera, renderer.domElement);
  controls.target.set(0, 10, 0);
  controls.update();

  // 创建地平面的几何体
  const planeGeometry = new THREE.PlaneGeometry(40, 40);
  const planeMaterial = new THREE.MeshLambertMaterial({ color: 0x001100 });
  const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);

  // 将地平面旋转90度，使其水平
  planeMesh.rotation.x = -Math.PI / 2;
  planeMesh.receiveShadow = true;

  scene.add(planeMesh);

  function render() {
    helper.update(clock.getDelta());
    renderer.render(scene, camera);
    frameId = requestAnimationFrame(render);
  }

  controls.addEventListener("change", render);

  // 设置GUI控制面板
  setupGUI();

  render();
});

onUnmounted(() => {
  cancelAnimationFrame(frameId);
  // 清理GUI
  if (gui) {
    gui.destroy();
  }
});
</script>

<style scoped>
#container {
  position: relative;
  width: 100vw;
  height: 100vh;
}
</style>
